Sample Display Library
Sample Display Library is a COM/DLL sample display and spectogram creator for use with BASS, for use in Win32 and Win64 (Windows XP/Vista/7/8/10) software.
Features:
- Create sample display and spectogram from various audio file formats BASS supports like MP3, Opus, FLAC, Ogg Vorbis and WAV format
- Multi-channel audio files are fully supported
- COM class usable by developer environments/platforms supporting COM classes like VBScript
- Full transparency support, anti-aliasing option, completely customizable colors (background, left and right channel)
- Power and PCM modes with multi-threading option
- Real-time mode for input recording and visualization
- Supports using the SampleDisplay.dll itself natively without COM, Delphi and C++ example included
- Delphi and C++ header file and tutorial included
If you are looking for a more precise and professional audio display component, check TGraphDisplay3D.
Requirements
Developer environment/platform supporting COM classes or DLLs.
Sample Display Library in freeware, shareware and commercial software?
The component can be freely evaluated. If you like it and use it in a freeware, shareware or commercial (or any other money making - advertising, in app. selling, etc.) product one of the licenses is needed.
Installation
Run an elevated command prompt, change dir into the folder where 'SampleDisplay.dll' is located, run the following: "regsvr32 SampleDisplay.dll". This should register the COM class. Do this for the desired Win32 and/or Win64 version.
bass.dll, bassmix.dll and FreeImage.dll is needed on the search path, eg. beside your .exe, or copy the needed DLLs to \Windows\System32\ (Win64 DLLs on a 64 bit OS) and/or \Windows\SysWOW64\ (Win32 DLLs on a 64 bit OS) folder. If the OS is 32 bit then copy the needed DLLs to \Windows\System32\ (from the Win32 folder). Win64 version also requires vcomp140.dll.
To use the library in VBScript, on a 64 bit OS, the VBScript process is 64 bit so the needed DLLs have to be from the Win64 folder, beside the .VBS file or in the System32 folder as written above.
Usage
After registering the DLL it can be accessed like:
createobject("SampleDisplay.CreateDisplay")
createobject("SampleDisplay.Spectogram")
VBScript usage example, 800 x 480 picture, dark color theme, 4x antialiasing, 32 bit PNG:
option explicit
dim myobject
set myobject = createobject("SampleDisplay.CreateDisplay")
myobject.LoadBASSFormatPlugin "bassflac.dll" 'optional, load needed BASS plugins here before calling 'CreatePicture()'
myobject.SetMode 0 'Mode '0' is default if not set, see below 'Sample display types'
myobject.SetDimensions 800, 480
myobject.SetColors &HFFFFFF00, &HFF00FF00, &HFF000000, &HFF888888, &HFF000000, &HFF000000, &HFF000000
myobject.SetCaption "My caption here for info"
myobject.SetAALevel 4
myobject.CreatePicture "D:\MP3z\Test.mp3", "D:\Test.png"
set myobject = nothing
VBScript usage example, 1024 x 480 picture, black background, red-orange color theme, &H80000003 means BASS_DATA_FFT2048 (available values are in bass.pas or Dynamic_bass.pas), limit the display to 5000 Hz, 32 bit PNG:
option explicit
dim myobject
set myobject = createobject("SampleDisplay.Spectogram")
myobject.SetDimensions 1024, 480
myobject.SetColors &HFF000000, 0.6, 1.0
myobject.SetParameters 5000, &H80000003
myobject.Margin = 10 'if this value is not set a default value of 5 will be used
myobject.CreateSpectogram "Test3.mp3", "Test3.mp3.png"
set myobject = nothing
Please see the Delphi tutorials on how to use the library with Delphi (and directly access the SampleDisplay.dll without COM).
- function CreatePicture (var Parameters: TSampleDisplayCreatePictureParameters): HResult; stdcall;
- 'SourceFileName' is the audio file from which the sample display picture is created.
- 'OutputFileName' is the file name of the generated PNG image.
- All colors are in (hex) AARRGGBB format.
- 'Caption' is an optional text that will be drawn at the bottom-left corner.
- 'Mode': see below section "Sample display types".
- 'AALevel' is antialiasing level, reasonable values 1-4 (1 means no antialiasing).
- Setting 'Quantize' to non-zero value will create 256 color PNG files.
- 'PenSize' in pixels, lowest value is 0.1.
- 'ShortModeSamplesTreshold' in samples, if the requested display contains less samples "short mode" is be used.
- 'Progress' is a callback for progress reporting. Set to nil if you don't wish to use a progress callback (using a callback is slower).
- function CreatePictureHandle (var Parameters: TSampleDisplayCreatePictureParameters; var BitmapHandle: THandle): HResult; stdcall;
- The parameters are same as above but this function returns a HBITMAP handle in 'BitmapHandle'.
Using SampleDisplay.dll natively: There are 4 exported functions:
- function SampleDisplay_CreatePicture(var Parameters: TSampleDisplayCreatePictureParameters): HResult; stdcall;
- function SampleDisplay_CreatePictureHandle(var Parameters: TSampleDisplayCreatePictureParameters; var BitmapHandle: THandle): HResult; stdcall;
- function SampleDisplay_CreateSpectogram(var Parameters: TSampleDisplayCreateSpectogramParameters): HResult; stdcall;
- If 'Width' = 0 is specified the function returns a picture with 1:1 width to FFT chunks size (the resulting picture will not be the specified width size but fully long as FFT chunks count).
- function SampleDisplay_CreateSpectogramHandle(var Parameters: TSampleDisplayCreateSpectogramParameters; var BitmapHandle: THandle): HResult; stdcall;
The 'TSampleDisplayCreatePictureParameters' structure size is 136 bytes for Win32 version and 176 bytes for the Win64 version (not packed).
The 'TSampleDisplayCreateSpectogramParameters' structure size is 88 bytes for Win32 version and 112 bytes for the Win64 version (not packed).
Sample display types
- Power mode: Mode = 0, an FFT is performed on the audio file and the frequency power values averaged per frame. This gives a display which shows the average audio power per frame. In case of stereo files the display is stereo, left channel values at top, right channel values at bottom. This mode is the slowest because an FFT is performed on the samples.
- Power mode threaded: Mode = 1, same as Power mode, but the audio file decoding and sampling is performed in multiple threads (as many CPU cores there are). The drawing and AA resampling of the final picture is performed in the calling thread. This mode is most suitable when not using AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
- Power mode threaded bitmaps: Mode = 2, same as Power mode. but the audio file decoding, sampling, drawing and AA resampling is performed in multiple threads (as many CPU cores there are). The result pictures from the threads are combined in the calling thread. This mode is most suitable for use with AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
- PCM mode: Mode = 3, the PCM values of the audio files are sampled and checked for highest value at intervals to fill the picture, the audio data is sampled from the source audio converted to mono. If the audio file sample count is lower or same as the picture width in pixels, then no highest value check will be used, the sample values are drawn exactly as their values, + values at top, - values at bottom.
- PCM mode threaded: Mode = 4, same as PCM mode, but the audio file decoding and sampling is performed in multiple threads (as many CPU cores there are). The drawing and AA resampling of the final picture is performed in the calling thread. This mode is most suitable when not using AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
- PCM mode threaded bitmaps: Mode = 5, same as PCM mode, but the audio file decoding, sampling, drawing and AA resampling is performed in multiple threads (as many CPU cores there are). The result pictures from the threads are combined in the calling thread. This mode is most suitable for use with AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
- PCM average mode: Mode = 6, same as PCM mode, but the sample values are averaged per column, min. and max. separatelly.
- PCM average mode threaded: Mode = 7, same as PCM average mode, but the audio file decoding and sampling is performed in multiple threads (as many CPU cores there are). The drawing and AA resampling of the final picture is performed in the calling thread. This mode is most suitable when not using AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
- PCM average mode threaded bitmaps: Mode = 8, same as PCM mode threaded bitmaps, but the sample values are averaged per column, min. and max. separatelly.
- PCM stereo mode: Mode = 9, the PCM values of the audio files are sampled and checked for highest value at intervals to fill the picture. The sample values are left channel at top, right channel at bottom.
- PCM stereo mode threaded: Mode = 10, same as PCM stereo mode, but the audio file decoding and sampling is performed in multiple threads (as many CPU cores there are). The drawing and AA resampling of the final picture is performed in the calling thread. This mode is most suitable when not using AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
- PCM stereo mode threaded bitmaps: Mode = 11, same as PCM stereo mode, but the audio file decoding, sampling, drawing and AA resampling is performed in multiple threads (as many CPU cores there are). The result pictures from the threads are combined in the calling thread. This mode is most suitable for use with AA and when the source audio files are long, ie. MP3 songs. Note that if the source audio files are short then the thread creation overhead may be more costly than not using multi-threading.
Note: Threaded modes will not give exactly the same picture because of number rounding effects.
Note: All PCM modes display amplitude scaled by * 0.95 to support AA and over-samples. If no AA is used and full (100%) samples height is needed, specify 'TSampleDisplayCreatePictureParameters.AmplitudeScale' as "1.0 / 0.95".
'PCM' mode for short (sample count / 2 < width by default) displays the waveform with perfect antialiasing and 'PenSize' thick line, a bitmap AA of "2" is recommended for perfect graphics. If the parameters are "sample count / 2 < width" (by default, can be set with 'ShortModeSamplesTreshold') then 'PCM' short mode is used.
Real-time functionality supports modes 0, 3, 6 and 9.
Using real-time is implemented separatelly for real-time functionality, using these modes require just a little CPU time and is super-smooth (mode 0 and 9 seems quite cool especially).
HResult error codes
- S_OK: Success.
- S_FALSE: Unknown error occured or catastrophic failure.
- 3: bass.dll or bassmix.dll could not be loaded.
- 4: The 'mode' value is out of range or not valid.
- 5: FreeImage.dll could not be loaded.
- 9: Input file could not be opened.
- 10: Output file could not be created.
- E_INVALIDARG: Parameters specified are invalid.
Progress callbacks
The assigned progress callbacks are called from the main thread only if the creation function is called from the main thread. The threaded modes call the progress callback from their threads, so then no UI access is allowed from the callback.
If progress reporting is needed when using threaded modes start the creation from a worker thread, so the UI can be refreshed when progress changes with sending a message to the main thread. Please see the 'Tutorial Sample Display' for an example.
The COM class expects a class that has implemented IProgress, the direct DLL calls expect a pointer to a simple function. Please see the 'Tutorial Sample Display' for an example.
All callback functions need to be of type 'stdcall' ('__stdcall' in C++).
Note that assigning a progress callback can significantly reduce performance.
Interactive tutorial
The interactive tutotial will work on max. sample count High(Integer). To support longer audio files adjust ScrollBar.Max and ScrollBar.PageSize to for example devide by 10, this will support 10x longer audio files but a little precision is lost. Ultimatelly use a scrollbar that supports 64 bit integer values.
When zooming and scrolling is needed it is strongly advised to convert the audio file to WAV first (for the display), else on every display change the whole (compressed) audio file needs to be decoded each time which is obviously very slow.
Hint: Create separate WAV files for each channel and use multiple displays to have a multi-channel display.
BASS format add-on plugins
To add an audio file format support for a specific format just call:
BASS_PluginLoad('bassflac.dll', BASS_UNICODE);
This will add support of loading that audio file format automatically.
BASS COM Management
BASSCOMManagement.dll first must be registered before using it, please see 'Installation' section.
BASS COM Management class should be used when running the COM classes in a multi-threded environment and using Sample Display Library together with for example BASS Encoder Library.
The individual components don't know of each other's state and they are both using BASS. To overcome this issue 'BASSCOMManagement.BASSManagement' COM class should be used when starting the process to initialize BASS for all the COM classes.
There are only 2 functions: 'BASSInitialize' and 'BASSFree'. 'BASSInitialize' expects only one parameter, the audio device number, it should be '0', the COM classes need to have BASS initialized for 0, the "no sound device".
When starting the process use:
option explicit
dim myobject
set myobject = createobject("BASSCOMManagement.BASSManagement")
myobject.BASSInitialize 0
set myobject=nothing
And just before the process exits call:
option explicit
dim myobject
set myobject = createobject("BASSCOMManagement.BASSManagement")
myobject.BASSFree
set myobject=nothing
The state is stored globally per process, and is valid until unloading the 'BASSCOMManagement.dll' from the process. Also the initialization and free calls are reference counted.
A simpler solution is to never free BASS - BASS will free itself when the BASS.dll is unloaded anyway. Use 'FreeBASS(1)' to set it to free it when freeing the Sample Display Library class. The default state is '0'.
When not using a scripting language it's only needed to call BASS_Init() manually (with device '0') on your program startup, and BASS_Free() on program exit, directly with BASS.dll.
Specifying a BASS channel handle as source
To send a BASS channel handle, use the 'SourceBASSHandle' variable, has priority over 'SourceFileName', or to use the 'SourceFileName':
FileName := PChar('BASSCHANNEL:' + IntToStr(Channel));
Notes:
1. The (mixer) channel needs to be positioned to the StartSample needed, to do this the code needs, for example, to BASS_ChannelGetData() until reaching the position. It's not possible to use BASS_ChannelSetPosition() with a mixer handle, so the component can not do that. It will start drawing the graphics from where the channel handle is currently when received.
2. When calling the function 'StartSample' only works if the channel handle is not a mixer handle, else has no effect.
3. 'Samples' must be not '0'.
4. This functionality is only available with non-threaded modes. As there is only 1 channel handle the component can not work with the channel handle from multiple threads. It's not possible to get samples from multiple threads from the same channel handle.
If the component is not able to get all the 'Samples' count samples the graphics will be stretched - should not happen if 'Samples' is a reasonable value.
Specifying an in-memory (WAV) file as source file name
For fast processing a file in memory is a good solution. For example create a WAV header and write the sample data after it. To use this memory "file" use the 'FileName' parameter like this:
FileName := PChar('POINTER:' + IntToStr(NativeUInt(FMemoryWAVStream.Memory)) + ',' + IntToStr(FMemoryWAVStream.Size));
Useful information
|